home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 020 / speechterm / term.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  22KB  |  862 lines

  1. #include <stdio.h>
  2. #include <exec/types.h>
  3. #include <exec/exec.h>
  4. #include <libraries/dos.h>
  5. #include <libraries/dosextens.h>
  6. #include <devices/serial.h>
  7.  
  8. #define MAX_CHARS 102
  9. #define SECSIZ 0x80
  10. #define TTIME 30
  11. #define BufSize 0x1000
  12. #define ERRORMAX 10
  13. #define RETRYMAX 10
  14. #define SOH 1
  15. #define EOT 4
  16. #define ACK 6
  17. #define CTRLQ (char)17
  18. #define CTRLS (char)19
  19. #define NAK 21
  20.  
  21. static char bufr[BufSize];
  22. static int fd, timeout = FALSE;
  23. static long bytes_xferred;
  24. static int oktosay = 1;
  25.  
  26. /*
  27.  * External functions
  28.  */
  29. extern   unsigned char        *stpblk();
  30. extern   unsigned char        *AllocMem();
  31. extern   struct   MsgPort     *CreatePort();
  32. extern   struct   FileHandle  *Open();
  33.  
  34. /*
  35.  * forward references
  36.  */
  37. int   define_function_key(), end(), help(), offline(), online(), sb(), rb(),
  38.       gfxoff(), speechon(), speechoff();
  39. /*
  40.  * Tables
  41.  */
  42. struct {
  43.    unsigned char  *cmdname;
  44.    int            (*cmdfunc)();
  45.    } command_table[] = {
  46.    (unsigned char *)"define", &define_function_key,
  47.    (unsigned char *)"def", &define_function_key,
  48.    (unsigned char *)"end", &end,
  49.    (unsigned char *)"help", &help,
  50.    (unsigned char *)"online", &online,
  51.    (unsigned char *)"on", &online,
  52.    (unsigned char *)"offline", &offline,
  53.    (unsigned char *)"off", &offline,
  54.    (unsigned char *)"gfxoff", &gfxoff,
  55.    (unsigned char *)"sb", &sb,
  56.    (unsigned char *)"rb", &rb,
  57.    (unsigned char *)"speechon", &speechon,
  58.    (unsigned char *)"speechoff", &speechoff,
  59.    (unsigned char *)"\0", &help,
  60.    };
  61.  
  62. unsigned char  *help_messages[] = {
  63.    "sb         = send file using Xmodem",
  64.    "rb         = receive file using Xmodem",
  65.    "def        = define a function key",
  66.    "define     = define a function key",
  67.    "end        = exit the program",
  68.    "help       = print this list",
  69.    "online     = enter or re-enter terminal mode",
  70.    "offline    = terminate communication",
  71.    "gfxoff     = terminate graphics",
  72.    "speechon   = permit speech",
  73.    "speechoff  = forbid speech",
  74.    0};
  75.  
  76. unsigned char  *function_key_definitions[20] = {
  77.    0,0,0,0,0,0,0,0,0,0,
  78.    0,0,0,0,0,0,0,0,0,0
  79.    };
  80.  
  81. /*
  82.  * Globals
  83.  */
  84. unsigned char     work[512];
  85. unsigned char     buf[512];
  86. unsigned char     iobuf[1024];
  87. int num_of_chars, no_io;
  88.  
  89. /*
  90.  * Terminal globals
  91.  */
  92. struct   FileHandle     *terminal_infp;
  93. struct   FileHandle     *terminal_outfp;
  94.  
  95. /*
  96.  * Terminal emulator stuff
  97.  */
  98. struct   Message        *mymessage;
  99. struct   IOExtSer       *ModemReadRequest;
  100. struct   IOExtSer       *ModemWriteRequest;
  101.  
  102. unsigned char  *WelcomeMessage = "Entering Terminal Mode\nUse ^C for command mode\n";
  103. unsigned char  *GoodbyeMessage = "Disconnected\n";
  104. unsigned char  *OfflineMessage = "--- Offline ---\n";
  105. unsigned char  *OnlineMessage = "--- Online ---\n";
  106.  
  107. unsigned char     rs_in[2], rs_out[2];
  108. int      bdoneflag = 0;
  109. int      TermEcho = 0;
  110. int      modem_online = 0;
  111.  
  112. static int gfx_flag;
  113.  
  114. main(argc, argv)
  115.   int   argc;
  116.   unsigned char  *argv[];
  117. {
  118.   gfx_flag = 0;
  119.   num_of_chars = 0;
  120.   no_io = 0;
  121.   sprintf(work, "Raw:0/0/640/200/Terminal");
  122.   terminal_infp = Open(work, MODE_NEWFILE);
  123.   if (terminal_infp == 0) {
  124.     printf("Can't open window\n");
  125.     exit(1);
  126.   }
  127.   terminal_outfp = terminal_infp;
  128.   sprintf(work, "\033[0x\033[0y\033[25t\033[80u\014");
  129.   WriteWork();
  130.  
  131.   while (1) {
  132.     Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
  133.     getcommand(buf);
  134.     CommandInterpreter(buf);
  135.   }
  136. }
  137.  
  138. WriteWork() {
  139.   Write(terminal_outfp, work, strlen(work));
  140. }
  141.  
  142. CommandInterpreter(command)
  143.   unsigned char  *command;
  144. {
  145.   int   i;
  146.  
  147.   command = stpblk(command);
  148.   /*
  149.    * Scan through the command table for the string and invoke the function
  150.    *    to do the actual work of the command.  Each of these commands is
  151.    *    defined below, and the functions each take a pointer to the
  152.    *    string containing the arguments passed the command line.
  153.    */
  154.   for (i=0; command_table[i].cmdname[0] != '\0'; i++)
  155.     if (strncmp(command, command_table[i].cmdname,
  156.                 strlen(command_table[i].cmdname)) == 0) {
  157.       (*command_table[i].cmdfunc)
  158.         (stpblk(&command[strlen(command_table[i].cmdname)]));
  159.       goto FinishedCommand;
  160.     }
  161.   /*
  162.    * Not found, so look for it on the disk.
  163.    */
  164.   executive(stpblk(&command[0]));
  165. FinishedCommand:
  166.   ;  /* Labels MUST be attached to some statement; even if the null stmt */
  167. }
  168.  
  169. executive(s)
  170.   unsigned char  *s;
  171. {
  172.   if (!Execute(s, 0, terminal_outfp))
  173.     printf("%d\n", IoErr());
  174. }
  175.  
  176. define_function_key(s)
  177. unsigned char  *s;
  178. {
  179.   int   i;
  180.  
  181.   if (s[0] == '\0')
  182.     for (i=0; i<20; i++) {
  183.       if (function_key_definitions[i]) {
  184.         sprintf(work, "F%-2d = %s\n", i+1, function_key_definitions[i]);
  185.         WriteWork();
  186.       }
  187.     }
  188.   else if (s[0] == 'f' || s[0] == 'F') {
  189.     s++;
  190.     i = atoi(s);
  191.     if (i < 1 || i > 20) {
  192.       sprintf(work, "%c[36mInvalid function key%c[0m\n", 0x1b, 0x1b);
  193.       WriteWork();
  194.     } else {
  195.       i--;
  196.       if (function_key_definitions[i])
  197.         FreeMem(function_key_definitions[i], strlen(function_key_definitions[i])+1);
  198.       while (isdigit(*s))
  199.         s++;
  200.       s = stpblk(s);
  201.       if (*s != '\0') {
  202.         function_key_definitions[i] = AllocMem(strlen(s)+1, MEMF_PUBLIC|MEMF_CLEAR);
  203.         if (function_key_definitions[i] == 0) {
  204.           sprintf(work, "%c[36mDefine Error: not enough memory%c[0m\n",
  205.                   0x1b, 0x1b);
  206.           WriteWork();
  207.         } else
  208.           strcpy(function_key_definitions[i], s);
  209.       }
  210.     }
  211.   } else {
  212.     sprintf(work,
  213.             "%c[36mDefine Error: invalid function key specified%c[0m\n",
  214.             0x1b, 0x1b);
  215.     WriteWork();
  216.   }
  217. }
  218.  
  219. end(s)
  220.   unsigned char  *s;
  221. {
  222.   if (modem_online) {
  223.     sprintf(work, "%c[36mTerminal Mode Error: Modem still online%c[0m\n",
  224.             0x1b, 0x1b);
  225.     WriteWork();
  226.   } else {
  227.     if (gfx_flag == 1)
  228.       terminate();
  229.     Close(terminal_outfp);
  230.     exit(0);
  231.   }
  232. }
  233.  
  234. help(s)
  235.   unsigned char  *s;
  236. {
  237.   int   i;
  238.  
  239.   sprintf(work,"%c[7m          MyCli Help          %c[0m\n", 0x1b, 0x1b);
  240.   WriteWork();
  241.   for (i=0; help_messages[i]; i++) {
  242.     sprintf(work, "%s\n", help_messages[i]);
  243.     WriteWork();
  244.   }
  245.   sprintf(work, "%c[7m          End of Help         %c[0m\n", 0x1b, 0x1b);
  246.   WriteWork();
  247. }
  248.  
  249. gfxoff()
  250. {
  251.   if (gfx_flag == 1)
  252.     terminate();
  253.   gfx_flag = 0;
  254. }
  255.  
  256. speechon()
  257. {
  258.   oktosay = 1;
  259. }
  260.  
  261. speechoff()
  262. {
  263.   oktosay = 0;
  264. }
  265.  
  266. offline(s)
  267. unsigned char  *s;
  268. {
  269.   modem_online = 0;
  270.   say_string((char*)0, 1);
  271. }
  272.  
  273. online(s)
  274.   unsigned char  *s;
  275. {
  276.   modem_online = !0;      /* signal that modem is live !!! */
  277.   if (initialize()) {     /* set baud rate, etc. */
  278.     Write(terminal_outfp, WelcomeMessage, strlen(WelcomeMessage));
  279.     while (modem_online) {
  280.       bdoneflag = 0;    /* terminal mode on flag */
  281.       Write(terminal_outfp, OnlineMessage, strlen(OnlineMessage));
  282.       while (!bdoneflag) {
  283.         check_keyboard();
  284.         check_modem();
  285.         if (bdoneflag || num_of_chars > MAX_CHARS || no_io > 0) {
  286.           if (num_of_chars > 0) {
  287.             Write(terminal_outfp, iobuf, num_of_chars);
  288.             num_of_chars = 0;
  289.           }
  290.         }
  291.       }
  292.       Write(terminal_outfp, OfflineMessage, strlen(OfflineMessage));
  293.       Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
  294.       getcommand(buf);
  295.       CommandInterpreter(buf);
  296.     }
  297.     cleanup();
  298.   }
  299.   modem_online = 0;
  300. }
  301.  
  302. getcommand(s)
  303.   unsigned char  *s;
  304. {
  305.   unsigned char  c;
  306.   unsigned col;
  307.  
  308.   col = 0;
  309.   while (1) {
  310.     Read(terminal_infp, &c, 1);
  311.     switch(c) {
  312.       case 8:
  313.         if (col) {
  314.           c = 8;
  315.           Write(terminal_outfp, &c, 1);
  316.           c = ' ';
  317.           Write(terminal_outfp, &c, 1);
  318.           c = 8;
  319.           Write(terminal_outfp, &c, 1);
  320.           col--;
  321.         }
  322.         continue;
  323.       case 10:
  324.       case 13:
  325.         sprintf(work, "\n");
  326.         WriteWork();
  327.         s[col++] = '\0';
  328.         break;
  329.       case 0x1b:
  330.       case 24:
  331.         while (col) {
  332.           c = 8;
  333.           Write(terminal_outfp, &c, 1);
  334.           c = ' ';
  335.           Write(terminal_outfp, &c, 1);
  336.           c = 8;
  337.           Write(terminal_outfp, &c, 1);
  338.           col--;
  339.         }
  340.         continue;
  341.       case 0x9b:
  342.         if (process_event(&s[col])) {
  343.           strcat(s, "\n");
  344.           Write(terminal_outfp, &s[col], strlen(&s[col]));
  345.           break;
  346.         }
  347.         continue;
  348.       default:
  349.         s[col++] = c;
  350.         Write(terminal_outfp, &c, 1);
  351.         continue;
  352.     }
  353.     break;
  354.   }
  355. }
  356.  
  357. /*
  358.  * this function converts an incoming ANSI escape sequence
  359.  * and processes it.  A buffer is passed where any function
  360.  * key expansion is to take place. If the buffer is modified
  361.  * for any reason, this function returns true.
  362.  */
  363. process_event(cmd_line)
  364.   unsigned char  *cmd_line;
  365. {
  366.   int   i;
  367.   unsigned char  c;
  368.   char  event_buffer[32];
  369.  
  370.   i = 0;
  371.   while (1) {
  372.     Read(terminal_infp, &c, 1);
  373.     event_buffer[i] = c;
  374.     if (c == '~' || c == '|' || c == 'A' || c == 'B' || c == 'C' || c == 'D')
  375.       break;
  376.     i++;
  377.   }
  378.   event_buffer[i+1] = '\0';
  379.   if (event_buffer[i] == '~') {
  380.     if (event_buffer[0] == '?') {
  381.       strcpy(cmd_line, "help");
  382.       return !0;
  383.     } else if (isdigit(event_buffer[0])) {
  384.       if (function_key(atoi(event_buffer), cmd_line))
  385.         return !0;
  386.       else if (atoi(event_buffer) == 6)
  387.         bdoneflag = !0;
  388.     }
  389.   } else if (i == 0 && (event_buffer[0] >= 'A' && event_buffer[0] <= 'D')) {
  390.     cmd_line[0] = '\033';
  391.     cmd_line[1] = event_buffer[0];
  392.     cmd_line[2] = '\000';
  393.     return !0;
  394.   }
  395.   return 0;
  396. }
  397.  
  398. /*
  399.  * if a definition for the function key fkey exists (0-19), then
  400.  * the translation for the function key is copied to the string
  401.  * s, and this function returns !0.  Otherwise, now translation
  402.  * exists, and this function returns 0.
  403.  */
  404. function_key(fkey, s)
  405.   int fkey;
  406.   unsigned char  *s;
  407. {
  408.   int   i;
  409.  
  410.   if (function_key_definitions[fkey] != 0) {
  411.     for (i=0; function_key_definitions[fkey][i] != '\0'; i++)
  412.       s[i] = function_key_definitions[fkey][i];
  413.     s[i] = '\0';
  414.     return !0;
  415.   }
  416.   return 0;
  417. }
  418.  
  419. initialize() {
  420.   ModemReadRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemReadRequest),
  421.                      MEMF_PUBLIC | MEMF_CLEAR);
  422.   ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  423.   ModemReadRequest->IOSer.io_Message.mn_ReplyPort =
  424.                                            CreatePort("Read_RS",0);
  425.   if (OpenDevice(SERIALNAME, NULL, ModemReadRequest, NULL)) {
  426.     sprintf(work, "%c[36mCan't open serial read device%c[0m\n",
  427.             0x1b, 0x1b);
  428.     WriteWork();
  429.     DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  430.     FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
  431.     return 0;
  432.   }
  433.   ModemReadRequest->IOSer.io_Command = CMD_READ;
  434.   ModemReadRequest->IOSer.io_Length = 1;
  435.   ModemReadRequest->IOSer.io_Data = (APTR) &rs_in[0];
  436.  
  437.   ModemWriteRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemWriteRequest),
  438.                       MEMF_PUBLIC | MEMF_CLEAR);
  439.   ModemWriteRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  440.   ModemWriteRequest->IOSer.io_Message.mn_ReplyPort =
  441.                                                  CreatePort("Write_RS",0);
  442.   if (OpenDevice(SERIALNAME, NULL, ModemWriteRequest, NULL)) {
  443.     sprintf(work, "%c[36mCan't open serial write device%c[0m\n",
  444.             0x1b, 0x1b);
  445.     WriteWork();
  446.     DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  447.     FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
  448.     DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
  449.     FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
  450.     return 0;
  451.   }
  452.   ModemWriteRequest->IOSer.io_Command = CMD_WRITE;
  453.   ModemWriteRequest->IOSer.io_Length = 1;
  454.   ModemWriteRequest->IOSer.io_Data = (APTR) &rs_out[0];
  455.  
  456.   ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  457.   ModemReadRequest->io_Baud = 1200;
  458.   ModemReadRequest->io_ReadLen = 8;
  459.   ModemReadRequest->io_WriteLen = 8;
  460.   ModemReadRequest->io_CtlChar = 1L;
  461.   ModemReadRequest->IOSer.io_Command = SDCMD_SETPARAMS;
  462.   DoIO(ModemReadRequest);
  463.   ModemReadRequest->IOSer.io_Command = CMD_READ;
  464.   BeginIO(ModemReadRequest);
  465.   return !0;
  466. }
  467.  
  468. cleanup() {
  469.   CloseDevice(ModemReadRequest);
  470.   DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
  471.   FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
  472.  
  473.   CloseDevice(ModemWriteRequest);
  474.   DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
  475.   FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
  476.  
  477.   Write(terminal_outfp, GoodbyeMessage, strlen(GoodbyeMessage));
  478. }
  479.  
  480. check_keyboard()
  481. {
  482.   unsigned char  *pc;
  483.  
  484.   if (WaitForChar(terminal_infp, 1)) {
  485.     Read(terminal_infp, &rs_out[0], 1);
  486.     switch ((unsigned char)rs_out[0]) {
  487.       case 0x9b:                          /* ANSI keyboard stuff */
  488.         if (process_event(&buf[0])) {    /* send the translation */
  489.           pc = &buf[0];
  490.           while (*pc != '\0') {
  491.             rs_out[0] = *pc++;
  492.             if (TermEcho)
  493.               Write(terminal_outfp, &rs_out[0], 1);
  494.             DoIO(ModemWriteRequest);
  495.             check_modem();
  496.           }
  497.         }
  498.         break;
  499.       case 0x05:                    /* toggle keystroke echo */
  500.         TermEcho = !TermEcho;
  501.         sprintf(work, "%c[36mEcho %s%c[0m\n", 0x1b, TermEcho?"ON":"OFF",
  502.                 0x1b);
  503.         WriteWork();
  504.         break;
  505.       default:
  506.         if (TermEcho)
  507.           Write(terminal_outfp, &rs_out[0], 1);
  508.         DoIO(ModemWriteRequest);
  509.     }
  510.   }
  511. }
  512.  
  513. /*
  514.  * Check to see if the Read Request IO has completed from the modem.
  515.  */
  516. check_modem()
  517. {
  518.   static int sayflag = 0;
  519.   static char saystring[133];
  520.   static int sayind = 0;
  521.   static int escape_sequence = 0;
  522.  
  523.   if (CheckIO(ModemReadRequest)) {
  524.     WaitIO(ModemReadRequest);
  525.     rs_in[0] &= 0x7f;
  526.  
  527.     if (rs_in[0] == '\001' && oktosay == 1) {
  528.       sayflag = 1;
  529.       BeginIO(ModemReadRequest);
  530.       return;
  531.     }
  532.  
  533.     if (oktosay == 1 && sayflag) {
  534.       if (rs_in[0] >= ' ' && rs_in[0] < (char)127) {
  535.         saystring[sayind++] = rs_in[0];
  536.       } else {
  537.     Write(terminal_outfp, iobuf, num_of_chars);
  538.     rs_out[0] = CTRLS;
  539.     DoIO(ModemWriteRequest);
  540.     num_of_chars = 0;
  541.         saystring[sayind++] = (char)0;
  542.         say_string(saystring,0);
  543.         sayind = 0;
  544.     sayflag = 0;
  545.     rs_out[0] = CTRLQ;
  546.     DoIO(ModemWriteRequest);
  547.       }
  548.     }
  549.     if (rs_in[0] == '\033') {
  550.       escape_sequence = 1;
  551.     } else if (escape_sequence == 1) {
  552.       if (rs_in[0] == 'G') {
  553.         Graphics();
  554.       } else {
  555.         iobuf[num_of_chars++] = '\033';
  556.         iobuf[num_of_chars++] = rs_in[0];
  557.         no_io = 0;
  558.       }
  559.       escape_sequence = 0;
  560.     } else {
  561.       iobuf[num_of_chars++] = rs_in[0];
  562.       no_io = 0;
  563.     }
  564.     BeginIO(ModemReadRequest);
  565.   } else {
  566.     no_io++;
  567.   }
  568. }
  569.  
  570. sendchar(ch)
  571.   int ch;
  572. {
  573.   rs_out[0] = ch;
  574.   DoIO(ModemWriteRequest);
  575. }
  576.  
  577. readchar()
  578. {
  579.   unsigned char c;
  580.   int rd,ch;
  581.   rd = FALSE;
  582.   while (rd == FALSE) {
  583.     if(CheckIO(ModemReadRequest)) {
  584.       WaitIO(ModemReadRequest);
  585.       ch=rs_in[0];
  586.       rd = TRUE;
  587.       BeginIO(ModemReadRequest);
  588.     }
  589.   }
  590.   if (rd == FALSE) {
  591.     timeout = TRUE;
  592.     emits("\nTimeout Waiting For Character\n");
  593.   }
  594.   c = ch;
  595.   return(c);
  596. }
  597.  
  598. rb(file)
  599.   char *file;
  600. {
  601.   int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
  602.   unsigned int checksum, j, bufptr,i;
  603.   char numb[10];
  604.   bytes_xferred = 0L;
  605.   i = 10;
  606.   if ((fd = creat(file, 0)) < 0) {
  607.     emits("Cannot Open File\n");
  608.     return FALSE;
  609.   } else
  610.     emits("Receiving File\n");
  611.   timeout=FALSE;
  612.   sectnum = errors = bufptr = 0;
  613.   sendchar(NAK);
  614.   firstchar = 0;
  615.   while (firstchar != EOT && errors != ERRORMAX) {
  616.     errorflag = FALSE;
  617.     do {
  618.       firstchar = readchar();
  619.       if (timeout == TRUE)
  620.         return FALSE;
  621.     }
  622.     while (firstchar != SOH && firstchar != EOT);
  623.     if (firstchar == SOH) {
  624.       emits("Getting Block ");
  625.       stci_d(numb,sectnum,i);
  626.       emits(numb);
  627.       emits("...");
  628.       sectcurr = readchar();
  629.       if (timeout == TRUE)
  630.         return FALSE;
  631.       sectcomp = readchar();
  632.       if (timeout == TRUE)
  633.         return FALSE;
  634.       if ((sectcurr + sectcomp) == 255) {
  635.         if (sectcurr == (sectnum + 1 & 0xff)) {
  636.           checksum = 0;
  637.           for (j = bufptr; j < (bufptr + SECSIZ); j++) {
  638.             bufr[j] = readchar();
  639.             if (timeout == TRUE)
  640.               return FALSE;
  641.             checksum = (checksum + bufr[j]) & 0xff;
  642.           }
  643.           if (checksum == readchar()) {
  644.             errors = 0;
  645.             sectnum++;
  646.             bufptr += SECSIZ;
  647.             bytes_xferred += SECSIZ;
  648.             emits("verified\n");
  649.             if (bufptr == BufSize) {
  650.               bufptr = 0;
  651.               if (write(fd, bufr, BufSize) == EOF) {
  652.                 emits("\nError Writing File\n");
  653.                 return FALSE;
  654.               };
  655.             };
  656.             sendchar(ACK);
  657.           } else {
  658.             errorflag = TRUE;
  659.             if (timeout == TRUE)
  660.               return FALSE;
  661.           }
  662.         } else {
  663.           if (sectcurr == (sectnum & 0xff)) {
  664.             emits("\nReceived Duplicate Sector\n");
  665.             sendchar(ACK);
  666.           } else
  667.             errorflag = TRUE;
  668.         }
  669.       } else
  670.          errorflag = TRUE;
  671.     }
  672.     if (errorflag == TRUE) {
  673.       errors++;
  674.       emits("\nError\n");
  675.       sendchar(NAK);
  676.     }
  677.   };
  678.   if ((firstchar == EOT) && (errors < ERRORMAX)) {
  679.     sendchar(ACK);
  680.     write(fd, bufr, bufptr);
  681.     write(fd, "\n", 1);
  682.     close(fd);
  683.     return TRUE;
  684.   }
  685.   return FALSE;
  686. }
  687.  
  688. sb(file)
  689.   char *file;
  690. {
  691.   int sectnum, bytes_to_send, size, attempts, c, i;
  692.   unsigned checksum, j, bufptr;
  693.   char numb[10];
  694.   timeout=FALSE;
  695.   bytes_xferred = 0;
  696.   i = 10;
  697.   if ((fd = open(file, 1)) < 0) {
  698.     emits("Cannot Open Send File\n");
  699.     return FALSE;
  700.   } else
  701.     emits("Sending File\n");
  702.   attempts = 0;
  703.   sectnum = 1;
  704.   j=1;
  705.   while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
  706.   if (j >= (ERRORMAX)) {
  707.     emits("\nReceiver not sending NAKs\n");
  708.     return FALSE;
  709.   };
  710.   while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
  711.   {
  712.     if (bytes_to_send == EOF) {
  713.       emits("\nError Reading File\n");
  714.       return FALSE;
  715.     };
  716.     bufptr = 0;
  717.     while (bytes_to_send > 0 && attempts != RETRYMAX) {
  718.       attempts = 0;
  719.       do {
  720.         sendchar(SOH);
  721.         sendchar(sectnum);
  722.         sendchar(~sectnum);
  723.         checksum = 0;
  724.         size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
  725.         bytes_to_send -= size;
  726.         for (j = bufptr; j < (bufptr + SECSIZ); j++)
  727.           if (j < (bufptr + size)) {
  728.             sendchar(bufr[j]);
  729.             checksum += bufr[j];
  730.           } else {
  731.             sendchar(0);
  732.           }
  733.         sendchar(checksum & 0xff);
  734.         attempts++;
  735.         c = readchar();
  736.         if (timeout == TRUE)
  737.           return FALSE;
  738.       } while ((c != ACK) && (attempts != RETRYMAX));
  739.       bufptr += size;
  740.       bytes_xferred += size;
  741.       emits("Block ");
  742.       stci_d(numb,sectnum,i);
  743.       emits(numb);
  744.       emits(" sent\n");
  745.       sectnum++;
  746.     }
  747.   }
  748.   close(fd);
  749.   if (attempts == RETRYMAX) {
  750.     emits("\nNo Acknowledgment Of Sector, Aborting\n");
  751.     return FALSE;
  752.   } else {
  753.     attempts = 0;
  754.     do {
  755.       sendchar(EOT);
  756.       attempts++;
  757.     } while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
  758.     if (attempts == RETRYMAX)
  759.       emits("\nNo Acknowledgment Of End Of File\n");
  760.   };
  761.   return TRUE;
  762. }
  763.  
  764. emits(embuf)
  765.   char *embuf;
  766. {
  767.   Write(terminal_outfp, embuf, strlen(embuf));
  768. }
  769.  
  770. Graphics()
  771. {
  772.   char buf[82], *gr_buf;
  773.   int gr_len, r, g, b, color, x1, y1, x2, y2;
  774.   int polx[256], poly[256], n, clip, xmin, ymin, xmax, ymax;
  775.   int i;
  776.  
  777.   if (gfx_flag == 0) {
  778.     gfx_flag = 1;
  779.     initialise();
  780.   } else
  781.     get_screen();
  782.   rs_out[0] = CTRLS;
  783.   DoIO(ModemWriteRequest);
  784.   BeginIO(ModemReadRequest);
  785.   for(;;) {
  786.     gr_len = 0;
  787.     buf[0] = (char)0;
  788.     gr_buf = &(buf[1]);
  789.     while(gr_buf[gr_len-1] != '\015') {
  790.       if (CheckIO(ModemReadRequest)) {
  791.         WaitIO(ModemReadRequest);
  792.         rs_in[0] &= 0x7f;
  793.         if (rs_in[0] != '\012') {
  794.           gr_buf[gr_len++] = rs_in[0];
  795.         }
  796.         BeginIO(ModemReadRequest);
  797.       } else {
  798.         rs_out[0] = CTRLQ;
  799.         DoIO(ModemWriteRequest);
  800.       }
  801.     }
  802.     rs_out[0] = CTRLS;
  803.     DoIO(ModemWriteRequest);
  804.     gr_buf[gr_len-1] = (char)0;
  805.     switch (gr_buf[0]) {
  806.       case 'T':
  807. /*        terminate(); */
  808.         put_screen();
  809.     rs_out[0] = CTRLQ;
  810.     DoIO(ModemWriteRequest);
  811.         return;
  812.       case 'C':
  813.         sscanf(&(gr_buf[1]), "%d%d%d%d", &color, &r, &g, &b);
  814.         define_color(color, r, g, b);
  815.         if (check_user_action() == -1) {
  816.           put_screen();
  817.           return;
  818.         }
  819.         break;
  820.       case 'L':
  821.         sscanf(&(gr_buf[1]), "%d%d%d%d%d", &x1, &y1, &x2, &y2, &color);
  822.         draw(x1, y1, x2, y2, color);
  823.         if (check_user_action() == -1) {
  824.           put_screen();
  825.           return;
  826.         }
  827.         break;
  828.       case 'P':
  829.         sscanf(&(gr_buf[1]), "%d%d%d%d%d%d%d", &n, &color, &clip,
  830.                            &xmin, &ymin, &xmax, &ymax);
  831.         for (i=0; i<n; i++) {
  832.           gr_len = 0;
  833.           buf[0] = (char)0;
  834.           gr_buf = &(buf[1]);
  835.           while(gr_buf[gr_len-1] != '\015') {
  836.             if (CheckIO(ModemReadRequest)) {
  837.               WaitIO(ModemReadRequest);
  838.               rs_in[0] &= 0x7f;
  839.               if (rs_in[0] != '\012') {
  840.                 gr_buf[gr_len++] = rs_in[0];
  841.               }
  842.               BeginIO(ModemReadRequest);
  843.             } else {
  844.           rs_out[0] = CTRLQ;
  845.           DoIO(ModemWriteRequest);
  846.         }
  847.           }
  848.           gr_buf[gr_len-1] = (char)0;
  849.       sscanf(gr_buf,"%d%d", &(polx[i]), &(poly[i]));
  850.         }
  851.     rs_out[0] = CTRLS;
  852.     DoIO(ModemWriteRequest);
  853. /*     poly_draw(polx, poly, n, color, clip, xmin, ymin, xmax, ymax); */
  854.         if (check_user_action() == -1) {
  855.           put_screen();
  856.           return;
  857.         }
  858.     break;
  859.     }
  860.   }
  861. }
  862.